<?php
/**
 * getFavicon
 * @author    一为
 * @date      2019-11-271
 * @link      https://www.iowen.cn
 * @version   1.2.9
 */

if( !isset($_GET['url'])){
    return http_response_code(404);
}

require "./Favicon.php";

$favicon = new \Jerrybendy\Favicon\Favicon;


/* ------ 参数设置 ------ */

$defaultIco='favicon.png';   //默认图标路径
$expire = 2592000;           //缓存有效期30天, 单位为:秒，为0时不缓存
$timeout = 30;               //获取图标超时时间，单位秒
$dns_timeout = 5;            //DNS解析超时时间，单位秒
$max_retries = 3;            //最大重试次数
$backup_dns_servers = ['1.1.1.1']; //只使用Cloudflare的DNS服务器
$debug = isset($_GET['debug']) ? true : false; //是否开启调试模式 /ico/get.php?debug=1&url=https://www.baidu.com
$verbose = isset($_GET['verbose']) ? true : false; //是否开启详细调试模式 /ico/get.php?debug=1&verbose=1&url=https://www.baidu.com
$read = isset($_GET['read']) ? true : false; //是否开启读取模式 /ico/get.php?read=1&url=https://www.baidu.com

/* ------ 参数设置 ------ */

/**
 * 设置默认图标
 */
$favicon->setDefaultIcon($defaultIco);

/**
 * 检测URL参数
 */
$url = $_GET['url'];

// 确保URL格式正确
if (!preg_match('/^https?:\/\//i', $url)) {
    $url = 'http://' . $url;
}

/*
 * 格式化 URL, 并尝试读取缓存
 */
$formatUrl = $favicon->formatUrl($url);

// 如果是读取模式，直接处理并返回JSON
if ($read) {
    // 获取HTML内容
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $formatUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout); // 设置连接超时时间
    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600); // DNS缓存10分钟
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // 允许重定向
    
    $response = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); // 获取最终URL（考虑重定向）
    
    // 检查是否是DNS解析错误
    $dns_error = false;
    $resolved_ip = null; // 存储成功解析的IP地址
    if ($curl_errno > 0) {
        $curl_error = curl_error($ch);
        // DNS解析错误的错误码通常是6（无法解析主机名）
        if ($curl_errno == 6) {
            $dns_error = true;
            $debugInfo['dns_error'] = true;
            $debugInfo['error_message'] = $curl_error;
            
            // 尝试使用备用DNS服务器
            curl_close($ch);
            
            $retry_count = 0;
            $dns_resolved = false;
            
            while (!$dns_resolved && $retry_count < $max_retries) {
                $retry_count++;
                $debugInfo['dns_retry'] = $retry_count;
                
                // 在重试前短暂延迟
                usleep(500000); // 500毫秒
                
                foreach ($backup_dns_servers as $dns_server) {
                    $parsed_url = parse_url($formatUrl);
                    $host = $parsed_url['host'];
                    
                    $debugInfo['dns_server_' . $retry_count] = $dns_server;
                    
                    // 尝试使用备用DNS服务器解析域名
                    $ip = gethostbyname($host);
                    if ($ip != $host) { // 如果解析成功
                        $resolved_ip = $ip; // 保存解析成功的IP
                        $debugInfo['resolved_ip'] = $resolved_ip;
                    }
                    
                    // 尝试使用备用DNS服务器解析域名
                    $ch = curl_init();
                    curl_setopt($ch, CURLOPT_URL, $formatUrl);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout);
                    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600);
                    
                    // 尝试使用CURLOPT_RESOLVE预设域名解析
                    if ($resolved_ip) {
                        curl_setopt($ch, CURLOPT_RESOLVE, [$host . ':' . (isset($parsed_url['port']) ? $parsed_url['port'] : ($parsed_url['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
                    }
                    
                    // 设置备用DNS服务器（如果cURL版本支持）
                    if (defined('CURLOPT_DNS_SERVERS')) {
                        curl_setopt($ch, CURLOPT_DNS_SERVERS, $dns_server);
                    }
                    
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
                    
                    if ($verbose) {
                        curl_setopt($ch, CURLOPT_HEADER, TRUE);
                    } else {
                        curl_setopt($ch, CURLOPT_HEADER, FALSE);
                    }
                    
                    $response = curl_exec($ch);
                    $curl_errno = curl_errno($ch);
                    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                    $finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
                    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                    
                    $debugInfo['dns_retry_' . $retry_count . '_status'] = $httpCode;
                    $debugInfo['dns_retry_' . $retry_count . '_errno'] = $curl_errno;
                    
                    // 如果成功解析，跳出循环
                    if ($curl_errno == 0) {
                        $dns_error = false;
                        $dns_resolved = true;
                        $debugInfo['dns_resolved'] = true;
                        $debugInfo['dns_resolved_by'] = $dns_server;
                        break;
                    }
                }
                
                if ($dns_resolved) {
                    break;
                }
            }
            
            if (!$dns_resolved) {
                $debugInfo['dns_resolution_failed'] = true;
            }
        }
    }
    
    $html = $response;
    curl_close($ch);
    
    // 准备返回数据
    $readInfo = [];
    $readInfo['url'] = $url;
    $readInfo['formatted_url'] = $formatUrl;
    $readInfo['final_url'] = $finalUrl;
    $readInfo['status'] = $httpCode;
    
    // 如果发生DNS错误，记录错误信息
    if ($dns_error) {
        $readInfo['dns_error'] = true;
        $readInfo['error_message'] = 'DNS解析失败，无法连接到服务器';
    }
    
    // 提取网站标题
    $title = '';
    if (!empty($html) && $httpCode == 200) {
        // 直接提取title标签内容
        if (preg_match('/<title>(.*?)<\/title>/si', $html, $matches)) {
            $title = $matches[1];
            // 清理标题文本
            $title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
            $title = preg_replace('/\s+/', ' ', $title); // 替换多个空白字符为单个空格
            $title = trim($title);
        }
        
        // 如果没有找到标题或标题为空，尝试其他方法
        if (empty($title)) {
            // 尝试使用更复杂的正则表达式
            $titlePatterns = [
                '/<title[^>]*>([\s\S]*?)<\/title>/i',
                '/<meta\s+property=["\'](og:title|twitter:title)["\'][^>]+content=["\']([\s\S]*?)["\']/i',
                '/<meta\s+name=["\'](title|twitter:title)["\'][^>]+content=["\']([\s\S]*?)["\']/i',
                '/<meta\s+content=["\']([\s\S]*?)["\'][^>]+property=["\'](og:title|twitter:title)["\']/i',
                '/<meta\s+content=["\']([\s\S]*?)["\'][^>]+name=["\'](title|twitter:title)["\']/i',
            ];
            
            foreach ($titlePatterns as $pattern) {
                if (preg_match($pattern, $html, $matches)) {
                    if (strpos($pattern, 'meta') !== false && count($matches) > 2) {
                        $title = trim($matches[2]);
                    } else {
                        $title = trim($matches[1]);
                    }
                    
                    $title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
                    $title = preg_replace('/\s+/', ' ', $title);
                    $title = trim($title);
                    
                    if (!empty($title)) {
                        break;
                    }
                }
            }
        }
        
        // 特殊处理慕课网
        if (strpos($finalUrl, 'imooc.com') !== false && (empty($title) || $title == 'Imooc')) {
            $title = '慕课网-程序员的梦工厂';
        }
    }
    $readInfo['title'] = $title;
    
    // 提取图标URL
    $iconUrl = null;
    if (!empty($html) && $httpCode == 200) {
        // 查找各种可能的图标链接
        $iconPatterns = [
            // 匹配带有rel="icon"或rel="shortcut icon"的链接，确保提取href属性
            '/<link[^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]+href=["\'](https?:\/\/[^"\']+)["\'][^>]*>/i',
            '/<link[^>]+href=["\'](https?:\/\/[^"\']+)["\'][^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]*>/i',
            
            // 匹配协议相对URL的图标链接
            '/<link[^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]+href=["\'](\/\/[^"\']+)["\'][^>]*>/i',
            '/<link[^>]+href=["\'](\/\/[^"\']+)["\'][^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]*>/i',
            
            // 匹配相对路径的图标链接
            '/<link[^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]+href=["\'](\/[^"\']+)["\'][^>]*>/i',
            '/<link[^>]+href=["\'](\/[^"\']+)["\'][^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]*>/i',
            
            // 匹配相对路径的图标链接（无前导斜杠）
            '/<link[^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]+href=["\']((?!https?:\/\/|\/\/)[^"\'\/][^"\']*)["\'][^>]*>/i',
            '/<link[^>]+href=["\']((?!https?:\/\/|\/\/)[^"\'\/][^"\']*)["\'][^>]+rel=["\'](icon|shortcut icon|Shortcut Icon)["\'][^>]*>/i',
            
            // 匹配Apple Touch图标
            '/<link[^>]+rel=["\'](apple-touch-icon|apple-touch-icon-precomposed)["\'][^>]+href=["\'](.*?)["\'][^>]*>/i',
            '/<link[^>]+href=["\'](.*?)["\'][^>]+rel=["\'](apple-touch-icon|apple-touch-icon-precomposed)["\'][^>]*>/i',
            
            // 匹配带有type="image/x-icon"的链接
            '/<link[^>]+type=["\'](image\/x-icon)["\'][^>]+href=["\'](.*?)["\'][^>]*>/i',
            '/<link[^>]+href=["\'](.*?)["\'][^>]+type=["\'](image\/x-icon)["\'][^>]*>/i',
        ];
        
        // 尝试匹配图标链接
        foreach ($iconPatterns as $pattern) {
            if (preg_match($pattern, $html, $matches)) {
                // 确保我们提取的是href属性的值
                // 如果模式是href在前，rel在后，则matches[1]是href值
                // 如果模式是rel在前，href在后，则matches[2]是href值
                if (strpos($pattern, 'href=["\']') < strpos($pattern, 'rel=["\']')) {
                    $iconUrl = $matches[1];
                } else {
                    $iconUrl = $matches[2];
                }
                break;
            }
        }
        
        // 如果没有找到图标，尝试使用更宽松的正则表达式
        if (!$iconUrl) {
            // 尝试匹配任何带有rel="icon"的链接，确保提取href属性
            if (preg_match('/<link[^>]+rel=["\']icon["\'][^>]+href=["\']([^"\']+)["\'][^>]*>/i', $html, $matches)) {
                $iconUrl = $matches[1];
            }
            // 尝试匹配任何带有favicon的链接，确保提取href属性
            else if (preg_match('/<link[^>]+href=["\']([^"\']*favicon[^"\']*)["\'][^>]*>/i', $html, $matches)) {
                $iconUrl = $matches[1];
            }
            // 尝试匹配任何带有type="image/x-icon"的链接，确保提取href属性
            else if (preg_match('/<link[^>]+type=["\']image\/x-icon["\'][^>]+href=["\']([^"\']+)["\'][^>]*>/i', $html, $matches)) {
                $iconUrl = $matches[1];
            }
            else if (preg_match('/<link[^>]+href=["\']([^"\']+)["\'][^>]+type=["\']image\/x-icon["\'][^>]*>/i', $html, $matches)) {
                $iconUrl = $matches[1];
            }
        }
        
        // 如果仍然没有找到图标，尝试直接获取网站根目录的favicon.ico
        if (!$iconUrl) {
            $parsedUrl = parse_url($formatUrl);
            $iconUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/favicon.ico';
        }
        
        // 处理相对URL
        if ($iconUrl) {
            if (substr($iconUrl, 0, 2) === '//') {
                // 处理协议相对URL（以//开头）
                $parsedUrl = parse_url($formatUrl);
                $iconUrl = $parsedUrl['scheme'] . ':' . $iconUrl;
            } else if (!preg_match('/^https?:\/\//i', $iconUrl)) {
                // 处理其他相对URL
                $parsedUrl = parse_url($formatUrl);
                $base = $parsedUrl['scheme'] . '://' . $parsedUrl['host'];
                
                // 如果有端口号，添加到base中
                if (isset($parsedUrl['port'])) {
                    $base .= ':' . $parsedUrl['port'];
                }
                
                if (substr($iconUrl, 0, 1) === '/') {
                    $iconUrl = $base . $iconUrl;
                } else if (substr($iconUrl, 0, 2) === './') {
                    // 处理以./开头的相对路径
                    $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '/';
                    if (empty($path) || $path === '/') {
                        $path = '/';
                        $iconUrl = $base . substr($iconUrl, 1); // 移除开头的.
                    } else {
                        $path = substr($path, 0, strrpos($path, '/') + 1);
                        $iconUrl = $base . $path . substr($iconUrl, 2); // 移除开头的./
                    }
                } else {
                    $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '/';
                    if (empty($path) || $path === '/') {
                        $path = '/';
                    } else {
                        $path = substr($path, 0, strrpos($path, '/') + 1);
                    }
                    $iconUrl = $base . $path . $iconUrl;
                }
            }
        }
    }
    
    $readInfo['icon_url'] = $iconUrl ?: '';
    
    // 输出JSON
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($readInfo, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

// 如果是调试模式，清除缓存
if ($debug) {
    $dir = 'cache';
    $f = parse_url($formatUrl)['host'];
    $a = $dir . '/' . $f . '.txt';
    if (file_exists($a)) {
        unlink($a);
    }
}

if($expire == 0){
    // 直接获取图标，不缓存
    try {
        $favicon->getFavicon($formatUrl, false);
    } catch (Exception $e) {
        // 如果获取失败，返回默认图标
        header('Content-Type: image/png');
        echo file_get_contents($defaultIco);
    }
    exit;
}
else{
    $defaultMD5 = md5(file_get_contents($defaultIco));
    
    $data = Cache::get($formatUrl, $defaultMD5, $expire);
    if ($data !== NULL && !$debug) {
        foreach ($favicon->getHeader() as $header) {
            @header($header);
        }
        echo $data;
        exit;
    }

    // 调试信息
    $debugInfo = [];
    $debugInfo['url'] = $url;
    $debugInfo['formatted_url'] = $formatUrl;
    
    // 初始化IP解析变量
    $resolved_ip = null;
    
    /**
     * 缓存中没有指定的内容时, 直接获取HTML并解析图标
     */
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $formatUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout); // 设置连接超时时间
    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600); // DNS缓存10分钟
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // 允许重定向
    curl_setopt($ch, CURLOPT_HEADER, FALSE); // 不获取头信息，避免某些网站的特殊响应格式
    
    // 获取头信息（如果是详细模式）
    if ($verbose) {
        curl_setopt($ch, CURLOPT_HEADER, TRUE);
    }
    
    $response = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curlError = $curl_errno ? curl_error($ch) : null;
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); // 获取最终URL（考虑重定向）
    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); // 获取内容类型
    
    // 检查是否是DNS解析错误
    $dns_error = false;
    if ($curl_errno > 0) {
        // DNS解析错误的错误码通常是6（无法解析主机名）
        if ($curl_errno == 6) {
            $dns_error = true;
            $debugInfo['dns_error'] = true;
            $debugInfo['error_message'] = $curlError;
            
            // 尝试使用备用DNS服务器
            curl_close($ch);
            
            $retry_count = 0;
            $dns_resolved = false;
            
            while (!$dns_resolved && $retry_count < $max_retries) {
                $retry_count++;
                $debugInfo['dns_retry'] = $retry_count;
                
                // 在重试前短暂延迟
                usleep(500000); // 500毫秒
                
                foreach ($backup_dns_servers as $dns_server) {
                    $parsed_url = parse_url($formatUrl);
                    $host = $parsed_url['host'];
                    
                    $debugInfo['dns_server_' . $retry_count] = $dns_server;
                    
                    // 尝试使用备用DNS服务器解析域名
                    $ip = gethostbyname($host);
                    if ($ip != $host) { // 如果解析成功
                        $resolved_ip = $ip; // 保存解析成功的IP
                        $debugInfo['resolved_ip'] = $resolved_ip;
                    }
                    
                    // 尝试使用备用DNS服务器解析域名
                    $ch = curl_init();
                    curl_setopt($ch, CURLOPT_URL, $formatUrl);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout);
                    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600);
                    
                    // 尝试使用CURLOPT_RESOLVE预设域名解析
                    if ($resolved_ip) {
                        curl_setopt($ch, CURLOPT_RESOLVE, [$host . ':' . (isset($parsed_url['port']) ? $parsed_url['port'] : ($parsed_url['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
                    }
                    
                    // 设置备用DNS服务器（如果cURL版本支持）
                    if (defined('CURLOPT_DNS_SERVERS')) {
                        curl_setopt($ch, CURLOPT_DNS_SERVERS, $dns_server);
                    }
                    
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
                    
                    if ($verbose) {
                        curl_setopt($ch, CURLOPT_HEADER, TRUE);
                    } else {
                        curl_setopt($ch, CURLOPT_HEADER, FALSE);
                    }
                    
                    $response = curl_exec($ch);
                    $curl_errno = curl_errno($ch);
                    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                    $finalUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
                    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                    
                    $debugInfo['dns_retry_' . $retry_count . '_status'] = $httpCode;
                    $debugInfo['dns_retry_' . $retry_count . '_errno'] = $curl_errno;
                    
                    // 如果成功解析，跳出循环
                    if ($curl_errno == 0) {
                        $dns_error = false;
                        $dns_resolved = true;
                        $debugInfo['dns_resolved'] = true;
                        $debugInfo['dns_resolved_by'] = $dns_server;
                        break;
                    }
                }
                
                if ($dns_resolved) {
                    break;
                }
            }
            
            if (!$dns_resolved) {
                $debugInfo['dns_resolution_failed'] = true;
            }
        }
    }
    
    // 检查是否是HTML内容
    $isHtml = false;
    if ($contentType && (strpos($contentType, 'text/html') !== false || strpos($contentType, 'application/xhtml+xml') !== false)) {
        $isHtml = true;
    } else if (!$contentType && $response) {
        // 如果没有内容类型，尝试通过内容判断
        $isHtml = (strpos($response, '<!DOCTYPE html>') !== false || strpos($response, '<html') !== false);
    }
    
    // 处理响应（分离头信息和HTML内容）
    if ($verbose && $isHtml && $response) {
        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $headerSize);
        $html = substr($response, $headerSize);
        $debugInfo['headers'] = $header;
    } else if ($isHtml && $response) {
        $html = $response;
    } else {
        // 如果不是HTML内容，可能是直接返回了图片或其他内容
        $html = '';
        // 检查是否是图片内容
        if ($contentType && (strpos($contentType, 'image/') !== false) && $response) {
            $content = $response; // 直接使用响应内容作为图标
            $debugInfo['direct_icon'] = true;
            $debugInfo['icon_type'] = $contentType;
            $debugInfo['icon_length'] = strlen($content);
        }
    }
    
    curl_close($ch);
    
    $debugInfo['html_status'] = $httpCode;
    $debugInfo['html_length'] = $response ? strlen($response) : 0;
    $debugInfo['final_url'] = $finalUrl;
    $debugInfo['content_type'] = $contentType;
    $debugInfo['is_html'] = $isHtml;
    if ($curlError) {
        $debugInfo['curl_error'] = $curlError;
    }
    
    // 如果URL被重定向，更新formatUrl
    if ($finalUrl !== $formatUrl) {
        $formatUrl = $finalUrl;
        $debugInfo['redirected'] = true;
    }
    
    // 如果已经直接获取到了图标内容，跳过HTML解析
    if (!isset($content)) {
        $iconUrl = null;
        $contentType = null;
        
        if (!empty($html) && $httpCode == 200 && $isHtml) {
            // 保存HTML片段用于调试
            if ($debug) {
                $debugInfo['html_sample'] = substr($html, 0, 1000) . '...';
            }
            
            // 查找各种可能的图标链接
            $iconPatterns = [
                // 匹配完整URL的图标链接（带引号）
                '/<link[^>]+rel=["\'](icon|shortcut icon)["\'][^>]+href=["\'](https?:\/\/[^"\']+)["\'][^>]*>/i',
                '/<link[^>]+href=["\'](https?:\/\/[^"\']+)["\'][^>]+rel=["\'](icon|shortcut icon)["\'][^>]*>/i',
                
                // 匹配完整URL的图标链接（不带引号）
                '/<link[^>]+rel=(icon|shortcut icon)[^>]+href=(https?:\/\/[^\s>]+)[^>]*>/i',
                '/<link[^>]+href=(https?:\/\/[^\s>]+)[^>]+rel=(icon|shortcut icon)[^>]*>/i',
                
                // 匹配协议相对URL的图标链接（带引号，以//开头）
                '/<link[^>]+rel=["\'](icon|shortcut icon)["\'][^>]+href=["\'](\/\/[^"\']+)["\'][^>]*>/i',
                '/<link[^>]+href=["\'](\/\/[^"\']+)["\'][^>]+rel=["\'](icon|shortcut icon)["\'][^>]*>/i',
                
                // 匹配协议相对URL的图标链接（不带引号，以//开头）
                '/<link[^>]+rel=(icon|shortcut icon)[^>]+href=(\/\/[^\s>]+)[^>]*>/i',
                '/<link[^>]+href=(\/\/[^\s>]+)[^>]+rel=(icon|shortcut icon)[^>]*>/i',
                
                // 匹配相对路径的图标链接（带引号）
                '/<link[^>]+rel=["\'](icon|shortcut icon)["\'][^>]+href=["\'](\/[^"\']+)["\'][^>]*>/i',
                '/<link[^>]+href=["\'](\/[^"\']+)["\'][^>]+rel=["\'](icon|shortcut icon)["\'][^>]*>/i',
                
                // 匹配相对路径的图标链接（不带引号）
                '/<link[^>]+rel=(icon|shortcut icon)[^>]+href=(\/[^\s>]+)[^>]*>/i',
                '/<link[^>]+href=(\/[^\s>]+)[^>]+rel=(icon|shortcut icon)[^>]*>/i',
                
                // 匹配相对路径的图标链接（无前导斜杠，带引号）
                '/<link[^>]+rel=["\'](icon|shortcut icon)["\'][^>]+href=["\']((?!https?:\/\/|\/\/)[^"\'\/][^"\']*)["\'][^>]*>/i',
                '/<link[^>]+href=["\']((?!https?:\/\/|\/\/)[^"\'\/][^"\']*)["\'][^>]+rel=["\'](icon|shortcut icon)["\'][^>]*>/i',
                
                // 匹配相对路径的图标链接（无前导斜杠，不带引号）
                '/<link[^>]+rel=(icon|shortcut icon)[^>]+href=((?!https?:\/\/|\/\/)[^\/\s>][^\s>]*)[^>]*>/i',
                '/<link[^>]+href=((?!https?:\/\/|\/\/)[^\/\s>][^\s>]*)[^>]+rel=(icon|shortcut icon)[^>]*>/i',
                
                // 匹配Apple Touch图标（带引号）
                '/<link[^>]+rel=["\'](apple-touch-icon|apple-touch-icon-precomposed)["\'][^>]+href=["\'](.*?)["\'][^>]*>/i',
                '/<link[^>]+href=["\'](.*?)["\'][^>]+rel=["\'](apple-touch-icon|apple-touch-icon-precomposed)["\'][^>]*>/i',
                
                // 匹配Apple Touch图标（不带引号）
                '/<link[^>]+rel=(apple-touch-icon|apple-touch-icon-precomposed)[^>]+href=([^\s>]+)[^>]*>/i',
                '/<link[^>]+href=([^\s>]+)[^>]+rel=(apple-touch-icon|apple-touch-icon-precomposed)[^>]*>/i',
                
                // 特别匹配简单的favicon链接
                '/<link\s+href=["\'](\/favicon\.ico)["\'](?:\s+rel=["\'](shortcut icon|icon)["\'])?[^>]*>/i',
                '/<link\s+rel=["\'](shortcut icon|icon)["\'](?:\s+href=["\'](\/favicon\.ico)["\'])?[^>]*>/i',
            ];
            
            // 保存所有匹配结果用于调试
            if ($debug) {
                $debugInfo['all_matches'] = [];
                foreach ($iconPatterns as $index => $pattern) {
                    if (preg_match_all($pattern, $html, $matches, PREG_SET_ORDER)) {
                        foreach ($matches as $match) {
                            $debugInfo['all_matches'][] = [
                                'pattern' => $index,
                                'match' => $match
                            ];
                        }
                    }
                }
            }
            
            // 尝试匹配图标链接
            foreach ($iconPatterns as $index => $pattern) {
                if (preg_match($pattern, $html, $matches)) {
                    // 确保我们提取的是href属性的值
                    // 如果模式是href在前，rel在后，则matches[1]是href值
                    // 如果模式是rel在前，href在后，则matches[2]是href值
                    if (strpos($pattern, 'href=["\']') < strpos($pattern, 'rel=["\']')) {
                        $iconUrl = $matches[1];
                    } else {
                        $iconUrl = $matches[2];
                    }
                    $debugInfo['matched_pattern'] = $index;
                    $debugInfo['matched_url'] = $iconUrl;
                    break;
                }
            }
            
            // 如果没有找到图标，尝试使用更宽松的正则表达式
            if (!$iconUrl) {
                // 尝试匹配任何带有rel="icon"的链接（带引号）
                if (preg_match('/<link[^>]+rel=["\']icon["\'][^>]+href=["\']([^"\']+)["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_1';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有rel=icon的链接（不带引号）
                else if (preg_match('/<link[^>]+rel=icon[^>]+href=([^\s>]+)[^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_2';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有type="image/x-icon"的链接
                else if (preg_match('/<link[^>]+type=["\']image\/x-icon["\'][^>]+href=["\']([^"\']+)["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_3';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有type=image/x-icon的链接（不带引号）
                else if (preg_match('/<link[^>]+type=image\/x-icon[^>]+href=([^\s>]+)[^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_4';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有type="image/ico"的链接
                else if (preg_match('/<link[^>]+type=["\']image\/ico["\'][^>]+href=["\']([^"\']+)["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_5';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有type=image/ico的链接（不带引号）
                else if (preg_match('/<link[^>]+type=image\/ico[^>]+href=([^\s>]+)[^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_6';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有favicon的链接
                else if (preg_match('/<link[^>]+href=["\']([^"\']*favicon[^"\']*)["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_7';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配任何带有favicon的链接（不带引号）
                else if (preg_match('/<link[^>]+href=([^\s>]*favicon[^\s>]*)[^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_8';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 特别匹配简单的favicon.ico链接
                else if (preg_match('/<link[^>]+href=["\'](\/favicon\.ico)["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_9';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配href在前，type在后的链接
                else if (preg_match('/<link[^>]+href=["\']([^"\']+)["\'][^>]+type=["\']image\/x-icon["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_10';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                // 尝试匹配href在前，rel在后的链接
                else if (preg_match('/<link[^>]+href=["\']([^"\']+)["\'][^>]+rel=["\']icon["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_11';
                    $debugInfo['matched_url'] = $iconUrl;
                }
                else if (preg_match('/<link[^>]+href=["\']([^"\']+)["\'][^>]+rel=["\']shortcut icon["\'][^>]*>/i', $html, $matches)) {
                    $iconUrl = $matches[1];
                    $debugInfo['matched_pattern'] = 'fallback_12';
                    $debugInfo['matched_url'] = $iconUrl;
                }
            }
            
            // 如果仍然没有找到图标，尝试直接获取网站根目录的favicon.ico
            if (!$iconUrl) {
                $parsedUrl = parse_url($formatUrl);
                $iconUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/favicon.ico';
                $debugInfo['matched_pattern'] = 'root_favicon';
                $debugInfo['matched_url'] = $iconUrl;
            }
            
            if ($iconUrl) {
                // 处理相对URL
                if (substr($iconUrl, 0, 2) === '//') {
                    // 处理协议相对URL（以//开头）
                    $parsedUrl = parse_url($formatUrl);
                    $iconUrl = $parsedUrl['scheme'] . ':' . $iconUrl;
                    $debugInfo['processed_url'] = $iconUrl;
                } else if (!preg_match('/^https?:\/\//i', $iconUrl)) {
                    // 处理其他相对URL
                    $parsedUrl = parse_url($formatUrl);
                    $base = $parsedUrl['scheme'] . '://' . $parsedUrl['host'];
                    
                    // 如果有端口号，添加到base中
                    if (isset($parsedUrl['port'])) {
                        $base .= ':' . $parsedUrl['port'];
                    }
                    
                    if (substr($iconUrl, 0, 1) === '/') {
                        $iconUrl = $base . $iconUrl;
                    } else if (substr($iconUrl, 0, 2) === './') {
                        // 处理以./开头的相对路径
                        $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '/';
                        if (empty($path) || $path === '/') {
                            $path = '/';
                            $iconUrl = $base . substr($iconUrl, 1); // 移除开头的.
                        } else {
                            $path = substr($path, 0, strrpos($path, '/') + 1);
                            $iconUrl = $base . $path . substr($iconUrl, 2); // 移除开头的./
                        }
                    } else {
                        $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '/';
                        if (empty($path) || $path === '/') {
                            $path = '/';
                        } else {
                            $path = substr($path, 0, strrpos($path, '/') + 1);
                        }
                        $iconUrl = $base . $path . $iconUrl;
                    }
                    $debugInfo['processed_url'] = $iconUrl;
                }
                
                // 获取图标
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $iconUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout);
                curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600);
                
                // 如果之前成功解析了域名，使用相同的IP
                if ($resolved_ip) {
                    $icon_parsed_url = parse_url($iconUrl);
                    $icon_host = $icon_parsed_url['host'];
                    
                    // 如果图标URL的主机名与原始URL相同，使用之前解析的IP
                    if ($icon_host == parse_url($formatUrl)['host']) {
                        curl_setopt($ch, CURLOPT_RESOLVE, [$icon_host . ':' . (isset($icon_parsed_url['port']) ? $icon_parsed_url['port'] : ($icon_parsed_url['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
                        $debugInfo['icon_using_resolved_ip'] = true;
                    }
                }
                
                // 设置备用DNS服务器（如果cURL版本支持）
                if (defined('CURLOPT_DNS_SERVERS')) {
                    curl_setopt($ch, CURLOPT_DNS_SERVERS, $backup_dns_servers[0]);
                }
                
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // 允许重定向
                
                // 获取头信息（如果是详细模式）
                if ($verbose) {
                    curl_setopt($ch, CURLOPT_HEADER, TRUE);
                }
                
                $iconResponse = curl_exec($ch);
                $iconCurlError = curl_errno($ch) ? curl_error($ch) : null;
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                $finalIconUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); // 获取最终图标URL
                
                // 处理响应（分离头信息和图标内容）
                if ($verbose) {
                    $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
                    $iconHeader = substr($iconResponse, 0, $headerSize);
                    $iconContent = substr($iconResponse, $headerSize);
                    $debugInfo['icon_headers'] = $iconHeader;
                } else {
                    $iconContent = $iconResponse;
                }
                
                $debugInfo['icon_status'] = $httpCode;
                $debugInfo['icon_type'] = $contentType;
                $debugInfo['icon_length'] = strlen($iconContent);
                $debugInfo['final_icon_url'] = $finalIconUrl;
                if ($iconCurlError) {
                    $debugInfo['icon_curl_error'] = $iconCurlError;
                    
                    // 如果获取图标失败，尝试使用备用DNS服务器
                    if (curl_errno($ch) == 6) { // DNS解析错误
                        $debugInfo['icon_dns_retry'] = true;
                        
                        curl_close($ch);
                        
                        // 尝试使用备用DNS服务器
                        foreach ($backup_dns_servers as $dns_server) {
                            $icon_parsed_url = parse_url($iconUrl);
                            $icon_host = $icon_parsed_url['host'];
                            
                            // 尝试再次解析域名
                            $icon_ip = gethostbyname($icon_host);
                            if ($icon_ip != $icon_host) { // 如果解析成功
                                $debugInfo['icon_resolved_ip'] = $icon_ip;
                                
                                $ch = curl_init();
                                curl_setopt($ch, CURLOPT_URL, $iconUrl);
                                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout);
                                curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600);
                                curl_setopt($ch, CURLOPT_RESOLVE, [$icon_host . ':' . (isset($icon_parsed_url['port']) ? $icon_parsed_url['port'] : ($icon_parsed_url['scheme'] == 'https' ? 443 : 80)) . ':' . $icon_ip]);
                                
                                if (defined('CURLOPT_DNS_SERVERS')) {
                                    curl_setopt($ch, CURLOPT_DNS_SERVERS, $dns_server);
                                }
                                
                                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                                curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
                                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
                                
                                $iconContent = curl_exec($ch);
                                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                                $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                                
                                $debugInfo['icon_retry_status'] = $httpCode;
                                $debugInfo['icon_retry_type'] = $contentType;
                                $debugInfo['icon_retry_length'] = strlen($iconContent);
                                
                                if (curl_errno($ch) == 0 && $httpCode == 200 && !empty($iconContent) && strlen($iconContent) > 100) {
                                    $debugInfo['icon_dns_retry_success'] = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                
                curl_close($ch);
                
                if ($httpCode == 200 && !empty($iconContent) && strlen($iconContent) > 100) {
                    $content = $iconContent;
                    // 不需要设置头信息，会在输出时自动设置
                } else if ($httpCode != 200 && strpos($iconUrl, '?') !== false) {
                    // 如果带查询参数的URL请求失败，尝试去掉查询参数再请求一次
                    $iconUrlWithoutQuery = strtok($iconUrl, '?');
                    $debugInfo['retry_without_query'] = $iconUrlWithoutQuery;
                    
                    $ch = curl_init();
                    curl_setopt($ch, CURLOPT_URL, $iconUrlWithoutQuery);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout);
                    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600);
                    
                    // 如果之前成功解析了域名，使用相同的IP
                    if ($resolved_ip) {
                        $icon_parsed_url = parse_url($iconUrlWithoutQuery);
                        $icon_host = $icon_parsed_url['host'];
                        
                        if ($icon_host == parse_url($formatUrl)['host']) {
                            curl_setopt($ch, CURLOPT_RESOLVE, [$icon_host . ':' . (isset($icon_parsed_url['port']) ? $icon_parsed_url['port'] : ($icon_parsed_url['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
                            $debugInfo['retry_using_resolved_ip'] = true;
                        }
                    }
                    
                    // 设置备用DNS服务器
                    if (defined('CURLOPT_DNS_SERVERS')) {
                        curl_setopt($ch, CURLOPT_DNS_SERVERS, $backup_dns_servers[0]);
                    }
                    
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
                    
                    $iconContent = curl_exec($ch);
                    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                    
                    $debugInfo['retry_status'] = $httpCode;
                    $debugInfo['retry_type'] = $contentType;
                    $debugInfo['retry_length'] = strlen($iconContent);
                    
                    curl_close($ch);
                    
                    if ($httpCode == 200 && !empty($iconContent) && strlen($iconContent) > 100) {
                        $content = $iconContent;
                    }
                }
            }
        } else if ($httpCode == 200 && !$isHtml && $response) {
            // 如果不是HTML但请求成功，可能是直接返回了图标
            $debugInfo['non_html_response'] = true;
            
            // 检查是否是图片内容
            if ($contentType && (strpos($contentType, 'image/') !== false)) {
                $content = $response; // 直接使用响应内容作为图标
                $debugInfo['direct_icon'] = true;
                $debugInfo['icon_type'] = $contentType;
                $debugInfo['icon_length'] = strlen($content);
            } else {
                // 尝试从URL中猜测图标
                $parsedUrl = parse_url($formatUrl);
                $iconUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/favicon.ico';
                $debugInfo['guessed_icon'] = $iconUrl;
                
                // 尝试获取猜测的图标
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $iconUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
                curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
                
                // 如果之前成功解析了域名，使用相同的IP
                if ($resolved_ip) {
                    curl_setopt($ch, CURLOPT_RESOLVE, [$parsedUrl['host'] . ':' . (isset($parsedUrl['port']) ? $parsedUrl['port'] : ($parsedUrl['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
                    $debugInfo['guessed_icon_using_resolved_ip'] = true;
                }
                
                $iconContent = curl_exec($ch);
                $iconHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $iconContentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                
                curl_close($ch);
                
                if ($iconHttpCode == 200 && !empty($iconContent) && strlen($iconContent) > 100) {
                    $content = $iconContent;
                    $contentType = $iconContentType;
                    $debugInfo['guessed_icon_status'] = $iconHttpCode;
                    $debugInfo['guessed_icon_type'] = $iconContentType;
                    $debugInfo['guessed_icon_length'] = strlen($iconContent);
                }
            }
        } else {
            // 请求失败或无内容，尝试直接获取favicon.ico
            $parsedUrl = parse_url($formatUrl);
            $iconUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/favicon.ico';
            $debugInfo['fallback_icon'] = $iconUrl;
            
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $iconUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
            
            // 如果之前成功解析了域名，使用相同的IP
            if ($resolved_ip) {
                curl_setopt($ch, CURLOPT_RESOLVE, [$parsedUrl['host'] . ':' . (isset($parsedUrl['port']) ? $parsedUrl['port'] : ($parsedUrl['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
                $debugInfo['fallback_icon_using_resolved_ip'] = true;
            }
            
            // 设置备用DNS服务器
            if (defined('CURLOPT_DNS_SERVERS')) {
                curl_setopt($ch, CURLOPT_DNS_SERVERS, $backup_dns_servers[0]);
            }
            
            $iconContent = curl_exec($ch);
            $iconHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $iconContentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
            
            curl_close($ch);
            
            if ($iconHttpCode == 200 && !empty($iconContent) && strlen($iconContent) > 100) {
                $content = $iconContent;
                $contentType = $iconContentType ?: 'image/x-icon';
                $debugInfo['fallback_icon_status'] = $iconHttpCode;
                $debugInfo['fallback_icon_type'] = $iconContentType;
                $debugInfo['fallback_icon_length'] = strlen($iconContent);
            }
        }
    }
    
    // 如果仍然没有获取到图标，尝试使用网站根目录的favicon.ico
    if (!isset($content)) {
        $parsedUrl = parse_url($formatUrl);
        $host = $parsedUrl['host'];
        $faviconUrl = $parsedUrl['scheme'] . '://' . $host . '/favicon.ico';
        
        $debugInfo['fallback_to_root_favicon'] = $faviconUrl;
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $faviconUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $dns_timeout);
        curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 600);
        
        // 如果之前成功解析了域名，使用相同的IP
        if ($resolved_ip) {
            curl_setopt($ch, CURLOPT_RESOLVE, [$host . ':' . (isset($parsedUrl['port']) ? $parsedUrl['port'] : ($parsedUrl['scheme'] == 'https' ? 443 : 80)) . ':' . $resolved_ip]);
            $debugInfo['root_favicon_using_resolved_ip'] = true;
        }
        
        // 设置备用DNS服务器
        if (defined('CURLOPT_DNS_SERVERS')) {
            curl_setopt($ch, CURLOPT_DNS_SERVERS, $backup_dns_servers[0]);
        }
        
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
        
        $faviconContent = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        
        $debugInfo['root_favicon_status'] = $httpCode;
        $debugInfo['root_favicon_type'] = $contentType;
        $debugInfo['root_favicon_length'] = strlen($faviconContent);
        
        curl_close($ch);
        
        if ($httpCode == 200 && !empty($faviconContent) && strlen($faviconContent) > 100) {
            $content = $faviconContent;
            $contentType = $contentType ?: 'image/x-icon';
            $debugInfo['fallback'] = 'root_favicon';
        }
    }
    
    // 如果仍然没有获取到图标，使用默认图标
    if (!isset($content)) {
        $content = file_get_contents($defaultIco);
        $contentType = 'image/png';
        $debugInfo['fallback'] = 'default_icon';
    }

    // 设置缓存过期时间
    $cacheExpire = $expire;
    if (md5($content) == $defaultMD5) {
        $cacheExpire = 43200; // 如果返回默认图标，设置过期时间为12小时
    }

    // 缓存图标
    if (!$debug) {
        Cache::set($formatUrl, $content, $cacheExpire);
    }

    // 如果是调试模式，输出调试信息
    if ($debug) {
        // 确保输出正确的JSON
        header('Content-Type: application/json; charset=utf-8');
        
        // 移除可能导致JSON编码问题的二进制数据
        if (isset($debugInfo['html_sample'])) {
            $debugInfo['html_sample'] = mb_convert_encoding($debugInfo['html_sample'], 'UTF-8', 'UTF-8');
        }
        if (isset($debugInfo['headers'])) {
            $debugInfo['headers'] = mb_convert_encoding($debugInfo['headers'], 'UTF-8', 'UTF-8');
        }
        if (isset($debugInfo['icon_headers'])) {
            $debugInfo['icon_headers'] = mb_convert_encoding($debugInfo['icon_headers'], 'UTF-8', 'UTF-8');
        }
        
        // 添加调试时间戳
        $debugInfo['debug_time'] = date('Y-m-d H:i:s');
        
        // 输出JSON
        echo json_encode($debugInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }

    // 设置正确的内容类型头
    if ($contentType) {
        header('Content-Type: ' . $contentType);
    } else {
        // 根据文件扩展名猜测内容类型
        $ext = strtolower(pathinfo($iconUrl, PATHINFO_EXTENSION));
        $contentTypeMap = [
            'ico' => 'image/x-icon',
            'png' => 'image/png',
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'gif' => 'image/gif',
            'svg' => 'image/svg+xml',
        ];
        if (isset($contentTypeMap[$ext])) {
            header('Content-Type: ' . $contentTypeMap[$ext]);
        } else {
            header('Content-Type: image/x-icon');
        }
    }

    // 输出图标
    echo $content;
    exit;
}


/**
 * 缓存类
 */
class Cache
{
    /**
     * 获取缓存的值, 不存在时返回 null
     *
     * @param $key
     * @param $default  默认图片
     * @param $expire   过期时间
     * @return string
     */
    public static function get($key, $default, $expire)
    {
        $dir = 'cache'; //图标缓存目录
       
        //$f = md5( strtolower( $key ) );
        $f = parse_url($key)['host'];

        $a = $dir . '/' . $f . '.txt';

        if(is_file($a)){
            $data = file_get_contents($a);
            if( md5($data) == $default ){
                $expire = 43200; //如果返回默认图标，过期时间为12小时。
            }
            if( (time() - filemtime($a)) > $expire ){
                return null;
            }
            else{
                return $data;
            }
		}
        else{
            return null;
        }
    }

    /**
     * 设置缓存
     *
     * @param $key
     * @param $value
     * @param $expire   过期时间
     */
    public static function set($key, $value, $expire)
    {
        $dir = 'cache'; //图标缓存目录
        
        //$f = md5( strtolower( $key ) );
        $f = parse_url($key)['host'];

        $a = $dir . '/' . $f . '.txt';
        
        //如果缓存目录不存在则创建
        if (!is_dir($dir)) mkdir($dir,0777,true) or die('创建缓存目录失败！');

        if ( !is_file($a) || (time() - filemtime($a)) > $expire ) {
            $imgdata = fopen($a, "w") or die("Unable to open file!");  //w  重写  a追加
            fwrite($imgdata, $value);
            fclose($imgdata); 
        }
    }
}
